home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Workbench Add-On
/
Workbench Add-On - Volume 1.iso
/
Dev
/
Oberon
/
source
/
OC
/
OCH.mod
< prev
next >
Wrap
Text File
|
1995-06-29
|
65KB
|
1,953 lines
(*************************************************************************
$RCSfile: OCH.mod $
Description: Code selection for statements
Created by: fjc (Frank Copeland)
$Revision: 5.25 $
$Author: fjc $
$Date: 1995/06/15 18:15:13 $
Copyright © 1990-1993, ETH Zuerich
Copyright © 1993-1995, Frank Copeland
This module forms part of the OC program
See OC.doc for conditions of use and distribution
Log entries are at the end of the file.
*************************************************************************)
<* STANDARD- *> <* MAIN- *> <*$ LongVars+ *>
MODULE OCH;
IMPORT SYS := SYSTEM, OCM, OCS, OCT, OCC, OCI, OCE, str := Strings;
(* --- Exported declarations ------------------------------------------ *)
TYPE
LabelRange * = RECORD
low *, high *, label * : LONGINT
END; (* LabelRange *)
(* --- Local declarations --------------------------------------------- *)
CONST
(* Symbols *)
null = OCS.null; times = OCS.times; slash = OCS.slash; div = OCS.div;
mod = OCS.mod; and = OCS.and; plus = OCS.plus; minus = OCS.minus;
or = OCS.or; eql = OCS.eql; neq = OCS.neq; lss = OCS.lss;
leq = OCS.leq; gtr = OCS.gtr; geq = OCS.geq; not = OCS.not;
(* object modes *)
Var = OCM.Var; VarX = OCM.VarX; Ind = OCM.Ind; IndX = OCM.IndX;
RegI = OCM.RegI; RegX = OCM.RegX; Lab = OCM.Lab; LabI = OCM.LabI;
Abs = OCM.Abs; Con = OCM.Con; Push = OCM.Push; Pop = OCM.Pop;
Coc = OCM.Coc; Reg = OCM.Reg; Fld = OCM.Fld; LProc = OCM.LProc;
XProc = OCM.XProc; TProc = OCM.TProc; AProc = OCM.AProc; Mod = OCM.Mod;
RList = OCM.RList; VarArg = OCM.VarArg; LibCall = OCM.LibCall;
M2Proc = OCM.M2Proc; CProc = OCM.CProc; Typ = OCM.Typ;
(* System flags *)
OberonFlag = OCM.OberonFlag; M2Flag = OCM.M2Flag; CFlag = OCM.CFlag;
BCPLFlag = OCM.BCPLFlag; AsmFlag = OCM.AsmFlag;
(* structure forms *)
Undef = OCT.Undef; Byte = OCT.Byte; Bool = OCT.Bool; Char = OCT.Char;
SInt = OCT.SInt; Int = OCT.Int; LInt = OCT.LInt; Real = OCT.Real;
LReal = OCT.LReal; Set = OCT.Set; String = OCT.String;
NilTyp = OCT.NilTyp; NoTyp = OCT.NoTyp; Pointer = OCT.Pointer;
ProcTyp = OCT.ProcTyp; Array = OCT.Array; DynArr = OCT.DynArr;
Record = OCT.Record; BSet = OCT.BSet; WSet = OCT.WSet;
PtrTyp = OCT.PtrTyp; AdrTyp = OCT.AdrTyp; BPtrTyp = OCT.BPtrTyp;
Word = OCT.Word; Longword = OCT.Longword; TagTyp = OCT.TagTyp;
caseSet = {Char, SInt, Int, LInt};
uptrSet = {M2Flag..AsmFlag};
intSet = {SInt, Int, LInt};
byteSet = {Undef, Bool, Byte, Char, SInt, BSet};
wordSet = {Int, WSet, Word};
lwordSet =
{ LInt, Real, LReal, Set, NilTyp, Pointer, ProcTyp,
PtrTyp, AdrTyp, BPtrTyp, Longword };
initSet = {Pointer, ProcTyp, PtrTyp, AdrTyp, BPtrTyp};
(* CPU Registers *)
D0 = 0; D1 = 1; D2 = 2; D7 = 7;
A0 = 8; A1 = 9; A2 = 10; A3 = 11; A4 = 12; A5 = 13; A6 = 14; A7 = 15;
BP = A4; FP = A5; SP = A7;
DataRegs = {D0 .. D7};
AdrRegs = {A0 .. A7};
(* Data sizes *)
B = 1; W = 2; L = 4;
VAR
returnFound : BOOLEAN;
(* --- Procedure declarations ----------------------------------------- *)
(*------------------------------------*)
PROCEDURE setCC (VAR x : OCT.Item; cc : LONGINT);
BEGIN (* setCC *)
x.typ := OCT.booltyp; x.mode := Coc; x.a0 := cc; x.a1 := 0; x.a2 := 0
END setCC;
(*------------------------------------*)
PROCEDURE FJ * (VAR loc : LONGINT);
BEGIN (* FJ *)
OCC.PutWord (OCC.BRA); OCC.PutWord (loc); loc := OCC.pc - 2
END FJ;
(*------------------------------------*)
PROCEDURE CFJ * (VAR x : OCT.Item; VAR loc : LONGINT);
VAR op : LONGINT;
BEGIN (* CFJ *)
IF x.typ.form = Bool THEN
IF x.mode = Con THEN
IF x.a0 = 0 THEN setCC (x, OCC.F) ELSE setCC (x, OCC.T) END
ELSIF x.mode # Coc THEN
OCC.PutF1 (OCC.TST, B, x); OCI.Unload (x); setCC (x, OCC.NE)
END
ELSE
OCS.Mark (120); setCC (x, OCC.EQ)
END;
IF x.a0 # OCC.T THEN
IF x.a0 = OCC.F THEN op := OCC.BRA
ELSE op := OCC.Bcc + (OCC.invertedCC (x.a0) * 100H);
END;
OCC.PutWord (op); OCC.PutWord (x.a2); loc := OCC.pc - 2
ELSE
loc := x.a2
END;
OCC.FixLink (x.a1)
END CFJ;
(*------------------------------------*)
PROCEDURE BJ * (loc : LONGINT);
VAR dest : LONGINT;
BEGIN (* BJ *)
dest := loc - OCC.pc - 2;
IF dest < -128 THEN OCC.PutWord (OCC.BRA); OCC.PutWord (dest)
ELSE OCC.PutWord (SYS.LOR (OCC.BRA, SYS.AND (dest, 0FFH)))
END
END BJ;
(*------------------------------------*)
PROCEDURE CBJ * (VAR x : OCT.Item; loc : LONGINT);
VAR op, dest : LONGINT;
BEGIN (* CBJ *)
IF x.typ.form = Bool THEN
IF x.mode = Con THEN
IF x.a0 = 0 THEN setCC (x, OCC.F) ELSE setCC (x, OCC.T) END
ELSIF x.mode # Coc THEN
OCC.PutF1 (OCC.TST, B, x); OCI.Unload (x); setCC (x, OCC.NE)
END
ELSE
OCS.Mark (120); setCC (x, OCC.EQ)
END;
IF x.a0 # OCC.T THEN
IF x.a0 = OCC.F THEN op := OCC.BRA
ELSE op := OCC.Bcc + (OCC.invertedCC (x.a0) * 100H);
END;
dest := loc - OCC.pc - 2;
IF dest < -128 THEN OCC.PutWord (op); OCC.PutWord (dest)
ELSE OCC.PutWord (SYS.LOR (op, SYS.AND (dest, 0FFH)))
END
END;
OCC.FixLinkWith (x.a2, loc); OCC.FixLink (x.a1)
END CBJ;
(*------------------------------------*)
PROCEDURE ModulePrologue * ();
VAR L1, L2 : LONGINT; label : OCT.Label;
BEGIN (* ModulePrologue *)
OCC.StartPrologue ();
IF OCS.option [OCS.main] THEN
IF OCM.SmallData THEN
NEW (label, 32); COPY ("_LinkerDB", label^);
OCC.PutWord (49F9H);
OCC.PutLongRef (0, label) (* LEA _LinkerDB,A4 *)
ELSIF OCM.Resident THEN
(* Allocate memory for the data segment *)
OCC.PutLong (048E7F0C0H); (* MOVEM.L D0-D3/A0-A1,-(A7) *)
(* Call e.AllocMem ( (__BSSLEN + 1) * 4, {e.memClear} ) *)
NEW (label, 32); COPY ("__BSSLEN", label^);
OCC.PutWord (0203CH);
OCC.PutLongRef (0, label); (* MOVE.L #__BSSLEN,D0 *)
OCC.PutWord (05280H); (* ADDQ.L #1,D0 *)
OCC.PutWord (0E580H); (* ASL.L #2,D0 *)
OCC.PutWord (02600H); (* MOVE.L D0,D3 *)
OCC.PutWord (07201H); (* MOVEQ.L #1,D1 *)
OCC.PutWord (04841H); (* SWAP D1 *)
OCC.PutLong (02C780004H); (* MOVE.L AbsExecBase,A6 *)
OCC.PutLong (04EAEFF3AH); (* JSR AllocMem(A6) *)
OCC.PutWord (04A80H); (* TST.L D0 *)
OCC.PutWord (0662CH); (* BNE continue *)
OCC.PutLong (02A6E0114H); (* MOVE.L 114(A6),A5 *)
OCC.PutLong (04AAD00ACH); (* TST.L AC(A5) *)
OCC.PutWord (0661AH); (* BNE bailout1 *)
OCC.PutLong (041ED005CH); (* LEA 5C(A5),A0 *)
OCC.PutLong (04EAEFE80H); (* JSR WaitPort(A6) *)
OCC.PutLong (041ED005CH); (* LEA 5C(A5),A0 *)
OCC.PutLong (04EAEFE8CH); (* JSR GetMsg(A6) *)
OCC.PutLong (0522E0127H); (* ADDQ.B #1,127(A6) *)
OCC.PutWord (02240H); (* MOVE.L D0,A1 *)
OCC.PutLong (04EAEFE86H); (* JSR ReplyMsg(A6) *)
(* bailout1: *)
OCC.PutLong (04CDF030FH); (* MOVEM.L (A7)+,D0-D3/A0-A1 *)
OCC.PutWord (07014H); (* MOVEQ #14,D0 *)
OCC.PutWord (04E75H); (* RTS *)
(* continue: *)
OCC.PutWord (02840H); (* MOVE.L D0,A4 *)
OCC.PutWord (02883H); (* MOVE.L D3,(A4) *)
OCC.PutLong (049EC0004H); (* LEA 4(A4),A4 *)
OCC.PutLong (04CDF030FH); (* MOVEM.L (A7)+,D0-D3/A0-A1 *)
END;
(* Push the address of the call to the cleanup code *)
OCC.PutWord (0487AH);
L1 := OCC.pc; OCC.PutWord (0); (* PEA ??(PC) *)
(* Call module Kernel initialisation code *)
IF ~OCM.Resident THEN
OCC.PutWord (07201H); (* MOVEQ #1,D1 *)
END;
OCC.CallKernel (OCC.kInit); (* Call Kernel_?INIT *)
IF ~OCM.Resident THEN
(* Check if we are already running *)
OCC.PutWord (04A01H); (* TST.B D1 *)
L2 := OCC.pc; OCC.PutWord (06600H); (* BNE bailout2 *)
END;
(* Branch to module initialisation code *)
IF OCM.SmallCode THEN
OCC.PutWord (OCC.BSR);
OCC.PutWordRef (0, OCT.InitLabel); (* BSR InitLabel *)
ELSE
OCC.PutWord (OCC.JSR + 039H);
OCC.PutLongRef (0, OCT.InitLabel); (* JSR InitLabel *)
END;
(* Set return code to 0 and make clean exit *)
OCC.PutWord (07000H); (* MOVEQ #0,D0 *)
OCC.PutWord (09138H); (* SUB.L A0,A0 *)
OCC.PutWord (07200H); (* MOVEQ #0,D1 *)
OCC.CallKernel (OCC.kHalt); (* Call Kernel_Halt *)
(* Fixup the cleanup code address pushed at the start *)
OCC.PatchWord (L1, OCC.pc - L1);
IF OCM.Resident THEN (* Free memory for data segment *)
OCC.PutWord (02600H); (* MOVE.L D0,D3 *)
OCC.PutLong (043ECFFFCH); (* LEA -4(A4),A1 *)
OCC.PutWord (02011H); (* MOVE.L (A1),D0 *)
OCC.PutLong (02C780004H); (* MOVE.L AbsExecBase,A6 *)
OCC.PutLong (04EAEFF2EH); (* JSR FreeMem(A6) *)
OCC.PutWord (02003H); (* MOVE.L D3,D0 *)
ELSE
(* Branch to module cleanup code *)
IF OCM.SmallCode THEN
OCC.PutWord (OCC.BSR);
OCC.PutWordRef (0, OCT.EndLabel) (* BSR EndLabel *)
ELSE
OCC.PutWord (OCC.JSR + 039H);
OCC.PutLongRef (0, OCT.EndLabel) (* JSR EndLabel *)
END;
(* Call module Kernel cleanup code *)
OCC.CallKernel (OCC.kEnd); (* Call Kernel_END *)
OCC.PutWord (4E75H); (* RTS *)
(* We are already running, so bail out with return code = 25 *)
OCC.PatchWord (L2, OCC.pc - L2 - 2); (* bailout2: *)
OCC.PutWord (588FH); (* ADDQ #4,A7 *)
OCC.PutWord (7019H); (* MOVEQ #25,D0 *)
END;
OCC.PutWord (4E75H) (* RTS *)
ELSE
(* Set a return code of 20 and return immediately. *)
OCC.PutWord (7014H); (* MOVEQ #20,D0 *)
OCC.PutWord (4E75H) (* RTS *)
END;
OCC.EndCodeHunk ()
END ModulePrologue;
(*------------------------------------*)
PROCEDURE StartProcedure * (proc : OCT.Object);
BEGIN (* StartProcedure *)
IF OCC.level = 1 THEN OCC.StartCodeHunk (FALSE) END
END StartProcedure;
(*------------------------------------*)
PROCEDURE LoadBP (saveBP : BOOLEAN);
BEGIN (* LoadBP *)
IF saveBP THEN OCC.PutWord (2F0CH) END; (* MOVE.L BP,-(SP) *)
OCC.PutWord (49F9H);
OCC.PutLongRef (0, OCT.VarLabel) (* LEA Module_VAR, BP *)
END LoadBP;
(*------------------------------------*)
PROCEDURE CopyDynArray (adr : LONGINT; typ : OCT.Struct; dsize : LONGINT);
VAR size, len, desc, ptr1, ptr2, tos, x : OCT.Item;
moveSize : INTEGER; moveWords, oddSize : BOOLEAN; R : OCC.RegState;
(*------------------------------------*)
PROCEDURE DynArrSize (typ : OCT.Struct);
BEGIN (* DynArrSize *)
IF typ.form = DynArr THEN
DynArrSize (typ.BaseTyp);
IF len.mode = Undef THEN
desc.mode := Var; desc.lev := OCC.level; desc.a0 := adr + typ.adr;
len.mode := Reg; len.a0 := D0; OCC.Move (L, desc, len);
desc.typ := OCT.linttyp; len.typ := OCT.linttyp
ELSE
IF desc.mode = Var THEN desc.a0 := adr + typ.adr;
ELSE desc.a1 := adr + typ.adr;
END;
OCE.Op (times, len, desc, TRUE)
END
ELSE
size.mode := Con; size.typ := OCT.linttyp; size.a0 := typ.size
END
END DynArrSize;
BEGIN (* CopyDynArray *)
IF OCS.pragma [OCS.saveRegs] OR OCS.pragma [OCS.saveAllRegs] THEN
OCS.Mark (345)
END;
R := OCC.regState; len.mode := Undef;
(* load total length of dyn array *)
DynArrSize (typ);
(* calculate size in bytes *)
oddSize := ODD (size.a0);
moveWords := ~oddSize & ((size.a0 MOD 4) # 0);
IF size.a0 > 1 THEN
OCE.Op (times, len, size, FALSE)
END;
IF oddSize THEN
x.mode := Con; x.a0 := 0; x.typ := OCT.inttyp;
OCC.Bit (OCC.BTST, x, len); (* BTST #0, <len> *)
OCC.PutWord (6702H); (* BEQ.S 1$ *)
OCC.PutF7 (OCC.ADDQ, L, 1, len) (* ADDQ.L #1, <len> *)
END; (* 1$ *)
size := len;
IF OCS.pragma [OCS.stackChk] THEN OCC.CallKernel (OCC.kStackChk) END;
(* adjust stack pointer *)
tos.mode := Reg; tos.a0 := SP;
OCC.PutF5 (OCC.SUB, L, size, tos); (* SUBA.L <size>, A7 *)
(* decrement counter *)
x.mode := Con; x.typ := OCT.inttyp;
IF ~oddSize THEN
(* adjust counter for copy loop *)
IF moveWords THEN x.a0 := 1 ELSE x.a0 := 2 END;
OCC.Shift (OCC.ASR, L, x, size); (* ASR.L #?, <size> *)
END;
OCC.PutF7 (OCC.SUBQ, L, 1, size); (* SUBQ.L #1, <size> *)
ptr1.mode := Ind; ptr1.a0 := adr; ptr1.a1 := 0; ptr1.a2 := -1;
ptr1.lev := OCC.level; ptr1.typ := OCT.notyp; ptr1.obj := NIL;
x := ptr1; x.mode := Var;
OCI.LoadAdr (ptr1); ptr1.mode := Pop; (* LEA adr(A5), An *)
OCC.ForgetReg (ptr1.a0);
OCC.Move (L, tos, x); (* MOVE.L A7, adr(A5) *)
OCC.GetAReg (ptr2, NIL);
OCC.Move (L, tos, ptr2); (* MOVE.L A7, Am *)
ptr2.mode := Pop;
IF oddSize THEN moveSize := B
ELSIF moveWords THEN moveSize := W
ELSE moveSize := L
END;
OCC.Move (moveSize, ptr1, ptr2); (* 2$ MOVE.? (An)+,(Am)+ *)
OCC.PutWord (OCC.DBF + size.a0);
OCC.PutWord (-4); (* DBF <size>, 2$ *)
OCC.FreeRegs (R)
END CopyDynArray;
(*------------------------------------*)
PROCEDURE StartProcBody * (proc : OCT.Object; dsize : LONGINT);
CONST
(* Register numbers in *reverse* order. *)
D0 = 15; D1 = 14; D2 = 13; D7 = 8;
A0 = 7; A1 = 6; A2 = 5; A4 = 3; A5 = 2; A6 = 1;
VAR
par : OCT.Object; x, y : OCT.Item; count : LONGINT;
usesA4, usesA5 : BOOLEAN; savedRegs : SET;
BEGIN (* StartProcBody *)
(*proc.a1 := OCC.pc;*)
OCC.StartProcedure (proc);
IF OCS.pragma [OCS.entryExitCode] THEN
IF OCS.pragma [OCS.stackChk] THEN
IF OCS.pragma [OCS.saveAllRegs] THEN
OCC.PutWord (2F00H) (* MOVE.L D0,-(A7) *)
END;
x.mode := Con; x.a0 := dsize; x.typ := OCT.linttyp;
y.mode := Reg; y.a0 := 0; (* D0 *)
OCC.Move (L, x, y); (* MOVE.L #dsize,D0 *)
OCC.CallKernel (OCC.kStackChk);
IF OCS.pragma [OCS.saveAllRegs] THEN
OCC.PutWord (201FH) (* MOVE.L (A7)+,D0 *)
END;
END; (* IF stackChk *)
usesA4 := ~OCS.pragma [OCS.longVars] & ~OCM.SmallData & ~OCM.Resident
& ( (proc.mode = XProc)
OR ((proc.mode = TProc) (*& (proc.visible = OCT.Exp)*) ));
usesA5 := (OCC.level # 1) OR (dsize # 0) OR OCT.IsParam (proc.link);
IF usesA4 THEN LoadBP (TRUE) END;
IF usesA5 THEN
IF
(dsize > 0)
& (OCS.option [OCS.initialise] OR OCS.pragma [OCS.clearVars])
THEN
OCC.PutWord (4E55H); OCC.PutWord (0); (* LINK A5,#0 *)
(* Clear all procedure variables. *)
count := dsize DIV 4; (* clear longwords initially *)
IF count > 0 THEN
IF count < 5 THEN (* inline the loop *)
WHILE count > 0 DO
OCC.PutWord (42A7H); (* CLR.L -(A7) *)
DEC (count)
END;
ELSE
IF OCS.pragma [OCS.saveAllRegs] THEN
OCC.PutWord (2F00H) (* MOVE.L D0,-(A7) *)
END;
OCC.PutWord (303CH);
OCC.PutWord (count - 1); (* MOVE.W #count-1,D0 *)
OCC.PutWord (42A7H); (* 1$ CLR.L -(A7) *)
OCC.PutWord (OCC.DBF);
OCC.PutWord (-4); (* DBF.W D0,1$ *)
IF OCS.pragma [OCS.saveAllRegs] THEN
OCC.PutWord (201FH) (* MOVE.L (A7)+,D0 *)
END;
END
END;
IF (dsize MOD 4) # 0 THEN (* Assuming dsize is a multiple of 2 *)
OCC.PutWord (4267H) (* CLR.W -(A7) *)
END
ELSE
OCC.PutWord (4E55H);
OCC.PutWord (-dsize); (* LINK A5,#<-dsize> *)
END
END; (* IF usesA5 *)
IF OCS.pragma [OCS.saveRegs] OR OCS.pragma [OCS.saveAllRegs] THEN
savedRegs := {A6..A2,D7..D2};
IF OCS.pragma [OCS.saveAllRegs] THEN
savedRegs := savedRegs + {A0,A1,D0,D1}
END;
IF usesA4 THEN EXCL (savedRegs, A4) END;
IF usesA5 THEN EXCL (savedRegs, A5) END;
OCC.PutWord (48E7H); (* MOVEM.L savedRegs,-(A7) *)
OCC.PutWord (SYS.VAL (LONGINT, savedRegs))
END; (* IF saveRegs OR saveAllRegs *)
IF OCS.pragma [OCS.copyArrays] THEN
par := proc.link;
WHILE par # NIL DO
(* code for dynamic array value parameters *)
IF (par.typ.form = DynArr) & (par.mode = Var) THEN
CopyDynArray (par.a0, par.typ, dsize)
END;
par := par.link
END
END; (* IF copyArrays *)
END; (* IF entryExitCode *)
returnFound := FALSE
END StartProcBody;
(*------------------------------------*)
PROCEDURE EndProcBody *
(proc : OCT.Object; psize : INTEGER; L0 : LONGINT; vars : BOOLEAN);
VAR op : OCT.Item; usesA4, usesA5 : BOOLEAN; savedRegs : SET;
BEGIN (* EndProcBody *)
IF OCS.pragma [OCS.entryExitCode] THEN
usesA4 := ~OCS.pragma [OCS.longVars] & ~OCM.SmallData & ~OCM.Resident
& ( (proc.mode = XProc)
OR ((proc.mode = TProc) (*& (proc.visible = OCT.Exp)*) ));
usesA5 := (OCC.level # 1) OR vars OR OCT.IsParam (proc.link);
IF usesA4 THEN
(* Don't count return address, frame pointer or global var base *)
DEC (psize, 12)
ELSE
(* Don't count return address or frame pointer *)
DEC (psize, 8)
END;
(* Insert trap for missing RETURN in function procedures. *)
IF (proc.typ # OCT.notyp) & OCS.pragma [OCS.returnChk] THEN
IF returnFound THEN OCC.Trap (OCC.ReturnCheck)
ELSE OCS.Mark (335)
END
END;
OCC.FixLink (L0); (* Fix up RETURN branches *)
IF OCS.pragma [OCS.saveRegs] OR OCS.pragma [OCS.saveAllRegs] THEN
savedRegs := {D2..D7,A2..A6};
IF OCS.pragma [OCS.saveAllRegs] THEN
savedRegs := savedRegs + {D0,D1,A0,A1}
END;
IF usesA4 THEN EXCL (savedRegs, A4) END;
IF usesA5 THEN EXCL (savedRegs, A5) END;
OCC.PutWord (4CDFH); (* MOVEM.L (A7)+,savedRegs *)
OCC.PutWord (SYS.VAL (LONGINT, savedRegs))
END;
IF usesA5 THEN OCC.PutWord (4E5DH) END; (* UNLK A5 *)
IF usesA4 THEN OCC.PutWord (285FH) END; (* MOVEA.L (A7)+, A4 *)
IF OCS.pragma [OCS.deallocPars] & (psize > 0) THEN
OCC.PutWord (2F57H); OCC.PutWord (psize); (* MOVE.L (SP),psize(SP) *)
IF psize <= 8 THEN
op.mode := Reg; op.a0 := SP;
OCC.PutF7 (OCC.ADDQ, L, psize, op) (* ADDQ #<psize>,SP *)
ELSE
OCC.PutWord (4FEFH); OCC.PutWord (psize)(* LEA psize(SP),SP *)
END
END;
OCC.PutWord (OCC.RTS);
END;
IF OCC.level = 1 THEN OCC.EndCodeHunk () END
END EndProcBody;
(*------------------------------------*)
PROCEDURE StartModuleBody * (VAR dsize : LONGINT; VAR L0 : LONGINT);
VAR
x, y, z : OCT.Item; modno : INTEGER; module : OCT.Module;
count : LONGINT; obj : OCT.Object; pushedModule : BOOLEAN;
name : ARRAY 256 OF CHAR;
(*------------------------------------*)
PROCEDURE CmdsAndTypes ( obj : OCT.Object );
VAR typ : OCT.Struct; len : LONGINT;
BEGIN (* CmdsAndTypes *)
IF obj # NIL THEN
CmdsAndTypes (obj.left);
IF obj.mode = Typ THEN
typ := obj.typ;
IF (typ # NIL) & (typ.form = Record) & (typ.sysflg = OberonFlag)
THEN
IF ~pushedModule THEN
OCC.PutWord (02F00H); (* MOVE.L D0,-(A7) *)
pushedModule := TRUE
END;
OCC.PutWord (02F17H); (* MOVE.L (A7),-(A7) *)
x.mode := Con; x.a0 := 0; x.typ := OCT.tagtyp;
x.label := typ.label;
OCC.PutF3 (OCC.PEA, x); (* PEA #Type descriptor *)
OCC.CallKernel (OCC.kRegisterType); (* Call RegisterType *)
END
ELSIF (obj.mode = XProc) & (obj.visible = OCT.Exp)
& (obj.typ = OCT.notyp) & (~OCT.IsParam (obj.link))
THEN
IF ~pushedModule THEN
OCC.PutWord (02F00H); (* MOVE.L D0,-(A7) *)
pushedModule := TRUE
END;
OCC.PutWord (02F17H); (* MOVE.L (A7),-(A7) *)
OCT.GetName (obj.name, name);
len := str.Length (name);
x.mode := Abs; x.a0 := len + 1; x.typ := OCT.linttyp;
OCC.PutF3 (OCC.PEA, x); (* PEA LEN(name) *)
OCC.AllocString (name, len, x);
x.mode := Con; x.typ := OCT.stringtyp;
OCC.PutF3 (OCC.PEA, x); (* PEA name *)
x.mode := Lab; x.a0 := 0; x.a1 := L; x.label := obj.label;
OCC.PutF3 (OCC.PEA, x); (* PEA command *)
OCC.CallKernel (OCC.kRegisterCommand); (* Call RegisterCommand *)
END;
CmdsAndTypes (obj.right)
END
END CmdsAndTypes;
BEGIN (* StartModuleBody *)
OCC.StartCodeHunk (TRUE);
IF ~OCM.SmallData & ~OCM.Resident & ~OCS.pragma [OCS.longVars] THEN
LoadBP (FALSE)
END;
(* Check if module already initialised *)
x.mode := Var; x.lev := 0; x.a0 := dsize; OCC.PutF1 (OCC.TST, B, x);
(* If so, return *)
L0 := 0; y.mode := Coc; y.a0 := OCC.EQ; y.a1 := 0; y.a2 := 0;
y.typ := OCT.booltyp; CFJ (y, L0);
(* Set initialisation flag *)
x.mode := Var; x.lev := 0; x.a0 := dsize; OCC.PutF3 (OCC.ST, x);
IF OCC.GlobalPtrs () THEN
x.mode := Var; x.lev := 0; x.a0 := 0;
OCC.PutF3 (OCC.PEA, x); (* PEA VARS *)
x.mode := Con; x.a0 := 0; x.a1 := 0; x.typ := OCT.tagtyp;
x.label := OCT.GCLabel;
OCC.PutF3 (OCC.PEA, x); (* PEA GC-Offsets *)
OCC.CallKernel (OCC.kInitGC) (* Call Kernel_InitGC *)
END;
IF OCS.option [OCS.register] THEN
(* Register the module, types and commands *)
x.mode := Abs; x.a0 := str.Length (OCT.ModuleName) + 1;
x.typ := OCT.linttyp;
OCC.PutF3 (OCC.PEA, x); (* PEA LEN(ModuleName) *)
x.mode := Con; x.a0 := 0; x.typ := OCT.stringtyp;
x.label := OCT.ConstLabel;
OCC.PutF3 (OCC.PEA, x); (* PEA #ModuleName *)
OCC.CallKernel (OCC.kRegisterModule); (* Call Kernel_RegisterModule *)
pushedModule := FALSE;
CmdsAndTypes (OCT.topScope.link);
IF pushedModule THEN
OCC.PutWord (0588FH) (* ADDQ.L #4,A7 *)
END
END;
IF (dsize > 0) & ~OCM.SmallData & ~OCM.Resident
& (OCS.option [OCS.initialise] OR OCS.pragma [OCS.clearVars])
THEN
OCC.GetAReg (x, NIL);
IF OCS.pragma [OCS.longVars] THEN
y.mode := Var; y.lev := 0; y.a0 := 0;
OCC.PutF2 (OCC.LEA, y, x.a0) (* LEA Module_VAR,An *)
ELSE
y.mode := Reg; y.a0 := BP;
OCC.Move (L, y, x) (* MOVE.L A4,An *)
END;
x.mode := Pop; count := dsize DIV 4; (* clear longwords initially *)
IF count > 0 THEN
IF count < 5 THEN (* inline the loop *)
WHILE count > 0 DO OCC.PutF1 (OCC.CLR, L, x); DEC (count) END;
ELSE
IF count > 65536 THEN OCS.Mark (312); count := 65536 END;
z.mode := Con; z.a0 := count - 1; z.typ := OCT.inttyp;
OCC.GetDReg (y, NIL);
OCC.Move (W, z, y); (* MOVE.W #count,Dn *)
OCC.PutF1 (OCC.CLR, L, x); (* 1$ CLR.L (An)+ *)
OCC.PutWord (OCC.DBF + y.a0);
OCC.PutWord (-4); (* DBF.W Dn,1$ *)
OCC.FreeReg (y)
END
END;
IF (dsize MOD 4) # 0 THEN (* Assuming dsize is a multiple of 2 *)
OCC.PutF1 (OCC.CLR, W, x) (* CLR.W (An)+ *)
END;
OCC.FreeReg (x)
END;
(* Increment dsize to account for initFlag variable *)
INC (dsize, OCM.BoolSize); IF ODD (dsize) THEN INC (dsize) END;
IF OCT.nofGmod > 0 THEN (* Initialise imported modules *)
IF ~OCM.SmallData & ~OCM.Resident & ~OCS.pragma [OCS.longVars] THEN
(* Save variable base pointer *)
OCC.PutWord (2F0CH) (* MOVE.L BP,-(SP) *)
END;
modno := 0;
WHILE modno < OCT.nofGmod DO
module := OCT.GlbMod [modno];
IF module.visible = OCT.Exp THEN
IF OCM.SmallCode THEN
OCC.PutWord (OCC.BSR); OCC.PutWordRef (0, module.label)
ELSE
OCC.PutWord (OCC.JSR + 039H); OCC.PutLongRef (0, module.label)
END;
END;
INC (modno)
END;
IF ~OCM.SmallData & ~OCM.Resident & ~OCS.pragma [OCS.longVars] THEN
(* Restore variable base pointer *)
OCC.PutWord (285FH) (* MOVEA.L (A7)+, A4 *)
END
END
END StartModuleBody;
(*------------------------------------*)
PROCEDURE EndModuleBody * (dsize : LONGINT; L0 : LONGINT);
VAR
x : OCT.Item; endProc : OCT.Object; modno : INTEGER;
module : OCT.Module;
BEGIN (* EndModuleBody *)
OCC.FixLink (L0);
OCC.PutWord (OCC.RTS);
IF ~OCM.Resident THEN
NEW (endProc);
endProc.mode := XProc; endProc.a0 := 0; endProc.typ := OCT.notyp;
endProc.label := OCT.EndLabel;
OCC.StartProcedure (endProc);
(* Clear initialisation flag *)
OCS.pragma [OCS.longVars] := TRUE;
x.mode := Var; x.lev := 0; x.a0 := dsize - 2; OCC.PutF3 (OCC.SF, x);
IF OCT.nofGmod > 0 THEN (* Cleanup imported modules *)
modno := 0;
WHILE modno < OCT.nofGmod DO
module := OCT.GlbMod [modno];
IF module.visible = OCT.Exp THEN
IF OCM.SmallCode THEN
OCC.PutWord (OCC.BSR); OCC.PutWordRef (0, module.endLab)
ELSE
OCC.PutWord (OCC.JSR + 039H); OCC.PutLongRef (0, module.endLab)
END;
END;
INC (modno)
END
END;
OCC.PutWord (OCC.RTS);
END;
OCC.EndCodeHunk ()
END EndModuleBody;
(*------------------------------------*)
PROCEDURE CompareParLists * (x, y : OCT.Object);
VAR xt, yt : OCT.Struct;
BEGIN (* CompareParLists *)
WHILE x # NIL DO
IF y # NIL THEN
xt := x.typ; yt := y.typ;
WHILE (xt.form = DynArr) & (yt.form = DynArr) DO
xt := xt.BaseTyp; yt := yt.BaseTyp
END;
IF x.mode # y.mode THEN
OCS.Mark (115)
ELSIF xt # yt THEN
IF (xt.form = ProcTyp) & (yt.form = ProcTyp) THEN
CompareParLists (xt.link, yt.link)
ELSE
OCS.Mark (115)
END
END;
y := y.link
ELSE OCS.Mark (116)
END;
x := x.link
END; (* WHILE *)
IF (y # NIL) & (y.mode <= Ind) & (y.a0 >= 0) THEN OCS.Mark (117) END
END CompareParLists;
(*------------------------------------*)
PROCEDURE Leng (VAR x : OCT.Item; L0 : LONGINT);
VAR y : OCT.Item;
BEGIN (* Leng *)
IF x.mode = Push THEN y.mode := Abs; y.a0 := L0; OCC.PutF3 (OCC.PEA, y)
ELSE y.mode := Con; y.a0 := L0; y.typ := OCT.linttyp; OCC.Move (L, y, x)
END
END Leng;
(*------------------------------------*)
PROCEDURE DynArrBnd (
ftyp : OCT.Struct; VAR ap : OCT.Item; varpar : BOOLEAN);
VAR
f : INTEGER; x, y, z, desc : OCT.Item; atyp : OCT.Struct;
adr : LONGINT; freeY : BOOLEAN;
BEGIN (* DynArrBnd *)
(* ftyp.form = DynArr *)
x.mode := Push; x.a0 := SP; atyp := ap.typ;
IF varpar & (ftyp.BaseTyp = OCT.bytetyp) THEN
IF atyp.form # DynArr THEN Leng (x, atyp.size)
ELSE
adr := atyp.adr; OCI.DescItem (desc, ap.desc, adr);
atyp := atyp.BaseTyp; freeY := FALSE;
IF atyp.form = DynArr THEN
OCC.GetDReg (y, NIL); OCC.Move (L, desc, y);
OCI.UpdateDesc (desc, adr); freeY := TRUE;
y.typ := OCT.linttyp;
REPEAT
OCI.DescItem (desc, ap.desc, atyp.adr);
OCE.Op (times, y, desc, FALSE);
atyp := atyp.BaseTyp
UNTIL atyp.form # DynArr;
ELSE
y := desc
END;
IF atyp.size > 1 THEN
z.mode := Con; z.a0 := atyp.size; z.typ := OCT.linttyp;
OCE.Op (times, y, z, FALSE)
END;
OCC.Move (L, y, x);
IF freeY THEN OCI.Unload (y) ELSE OCI.UnloadDesc (ap) END
END
ELSE
desc.mode := Undef;
LOOP
f := atyp.form;
IF f = Array THEN Leng (x, atyp.n)
ELSIF f = DynArr THEN
OCI.DescItem (desc, ap.desc, atyp.adr);
OCC.Move (L, desc, x); OCI.UpdateDesc (desc, atyp.adr)
ELSE OCS.Mark (66)
END;
ftyp := ftyp.BaseTyp; atyp := atyp.BaseTyp;
IF ftyp.form # DynArr THEN
IF ftyp # atyp THEN OCS.Mark (67) END;
EXIT
END
END; (* LOOP *)
OCI.UnloadDesc (ap)
END
END DynArrBnd;
(*------------------------------------*)
PROCEDURE ExtendStack (size : LONGINT);
VAR sp, x : OCT.Item;
BEGIN (* ExtendStack *)
sp.mode := Reg; sp.a0 := SP;
IF ODD (size) THEN INC (size) END;
IF size <= 8 THEN
OCC.PutF7 (OCC.SUBQ, L, size, sp)
ELSE
x.mode := RegI; x.a0 := SP; x.a1 := -size;
OCC.PutF2 (OCC.LEA, x, sp.a0)
END
END ExtendStack;
(*------------------------------------*)
PROCEDURE moveBW (VAR src, dst : OCT.Item; extend : BOOLEAN);
VAR x, zero : OCT.Item;
BEGIN (* moveBW *)
IF src.mode = Con THEN
OCC.Move (W, src, dst)
ELSE
IF ~extend THEN
zero.mode := Con; zero.a0 := 0; zero.typ := OCT.wordtyp;
END;
IF (dst.mode = Reg) & (dst.a0 IN DataRegs) THEN
IF ~extend THEN OCC.Move (W, zero, dst) END;
OCC.Move (B, src, dst);
IF extend THEN OCI.EXT (W, dst.a0) END
ELSE
IF extend THEN
OCI.Load (src); OCI.EXT (W, src.a0)
ELSE
x := src; OCC.GetDReg (src, NIL);
OCC.Move (W, zero, src); OCC.Move (B, x, dst); OCI.Unload (x)
END;
OCC.Move (W, src, dst)
END
END
END moveBW;
(*------------------------------------*)
PROCEDURE moveBL (VAR src, dst : OCT.Item; extend : BOOLEAN);
VAR x, zero : OCT.Item;
BEGIN (* moveBL *)
IF src.mode = Con THEN
OCC.Move (L, src, dst)
ELSE
IF ~extend THEN
zero.mode := Con; zero.a0 := 0; zero.typ := OCT.wordtyp;
END;
IF (dst.mode = Reg) & (dst.a0 IN DataRegs) THEN
IF ~extend THEN OCC.Move (L, zero, dst) END;
OCC.Move (B, src, dst);
IF extend THEN OCI.EXT (W, dst.a0); OCI.EXT (L, dst.a0) END
ELSE
IF extend THEN
OCI.Load (src); OCI.EXT (W, src.a0); OCI.EXT (L, src.a0)
ELSE
x := src; OCC.GetDReg (src, NIL);
OCC.Move (L, zero, src); OCC.Move (B, x, src); OCI.Unload (x)
END;
OCC.Move (L, src, dst)
END
END
END moveBL;
(*------------------------------------*)
PROCEDURE moveWL (VAR src, dst : OCT.Item; extend : BOOLEAN);
VAR x, zero : OCT.Item;
BEGIN (* moveWL *)
IF src.mode = Con THEN
OCC.Move (L, src, dst)
ELSE
IF ~extend THEN
zero.mode := Con; zero.a0 := 0; zero.typ := OCT.wordtyp;
END;
IF (dst.mode = Reg) & (dst.a0 IN DataRegs) THEN
IF ~extend THEN OCC.Move (L, zero, dst) END;
OCC.Move (W, src, dst);
IF extend THEN OCI.EXT (L, dst.a0) END
ELSE
IF extend THEN
OCI.Load (src); OCI.EXT (L, src.a0)
ELSE
x := src; OCC.GetDReg (src, NIL);
OCC.Move (L, zero, src); OCC.Move (W, x, src); OCI.Unload (x)
END;
OCC.Move (L, src, dst)
END
END
END moveWL;
(*------------------------------------*)
(*
Moves size bytes from src to dst.
*)
PROCEDURE moveBlock (VAR src, dst : OCT.Item; size : LONGINT);
VAR
x, y : OCT.Item; numRegs, i, s : INTEGER; lw : LONGINT; R : SET;
useMOVEM, freeDst : BOOLEAN;
BEGIN (* moveBlock *)
freeDst := FALSE;
(* size must be even, but it may be zero *)
IF ODD (size) THEN OCS.Mark (957); INC (size) END;
IF size = 2 THEN OCC.Move (W, src, dst)
ELSIF size = 4 THEN OCC.Move (L, src, dst)
ELSIF size > 0 THEN
R := {D0 .. D7} - OCC.regState.regs; numRegs := 0; i := D0;
WHILE i <= D7 DO IF i IN R THEN INC (numRegs) END; INC (i) END;
IF (size MOD 4) = 2 THEN useMOVEM := ((numRegs * 2) >= size); s := W
ELSE useMOVEM := ((numRegs * 4) >= size); s := L
END;
IF useMOVEM THEN
(* Calculate which registers are needed *)
numRegs := SHORT (size DIV s); i := D0;
WHILE numRegs > 0 DO
WHILE ~(i IN R) DO INC (i) END;
INC (i); DEC (numRegs)
END;
(* Discard the rest *)
WHILE i <= D7 DO EXCL (R, i); INC (i) END;
(* Reserve the registers *)
OCC.regState.regs := OCC.regState.regs + R;
FOR i := D0 TO D7 DO IF i IN R THEN OCC.ForgetReg (i) END END;
(* Finally ... *)
x.mode := RList; x.a0 := SYS.VAL (LONGINT, R);
OCC.Move (s, src, x); (* MOVEM.s <src>,Dx-Dy *)
OCC.Move (s, x, dst); (* MOVEM.s Dx-Dy,<dst> *)
(* Free registers. *)
OCC.regState.regs := OCC.regState.regs - R;
ELSE
OCI.LoadAdr (src); src.mode := Pop; OCC.ForgetReg (src.a0);
IF dst.mode = Push THEN
ExtendStack (size);
y.mode := Reg; y.a0 := dst.a0;
OCC.GetAReg (dst, NIL); OCC.Move (L, y, dst);
dst.mode := Pop; dst.a1 := 0;
freeDst := TRUE
ELSE
OCI.LoadAdr (dst); dst.mode := Pop; OCC.ForgetReg (dst.a0)
END;
lw := size DIV 4;
IF lw > 65536 THEN
x.mode := Con; x.a0 := lw; x.typ := OCT.linttyp;
OCI.Load (x); (* MOVE.L #<size>,Dc *)
OCC.Move (L, src, dst); (* 1$ MOVE.L (As)+,(Ad)+ *)
OCC.PutF7 (OCC.SUBQ, L, 1, x); (* SUBQ.L #1,Dc *)
OCC.PutWord (66FAH); (* BNE 1$ *)
ELSIF lw > 1 THEN
IF lw > 32768 THEN DEC (lw, 65536) END;
x.mode := Con; x.a0 := lw - 1; x.typ := OCT.inttyp;
OCI.Load (x); (* MOVE.W #<size>,Dc *)
OCC.Move (L, src, dst); (* 1$ MOVE.L (As)+,(Ad)+ *)
OCC.PutWord (OCC.DBF + x.a0);
OCC.PutWord (-4) (* DBF.W Dc, 1$ *)
ELSIF lw = 1 THEN
OCC.Move (L, src, dst)
END;
IF (size MOD 4) = 2 THEN OCC.Move (W, src, dst) END;
IF freeDst THEN OCC.FreeReg (dst) END
END
END
END moveBlock;
(*------------------------------------*)
PROCEDURE movePtr ( VAR src, dst : OCT.Item );
VAR x : OCT.Item;
BEGIN (* movePtr *)
IF (dst.typ.sysflg = BCPLFlag) & (src.typ.sysflg # BCPLFlag) THEN
x := src; OCC.GetDReg (src, NIL);
OCC.Move (L, x, src); (* MOVE.L src,Dx *)
x.mode := Con; x.a0 := 2; x.typ := OCT.linttyp;
OCC.Shift (OCC.ASR, L, x, src); (* ASR.L #2,Dx *)
ELSIF (dst.typ.sysflg # BCPLFlag) & (src.typ.sysflg = BCPLFlag) THEN
x := src; OCC.GetDReg (src, NIL);
OCC.Move (L, x, src); (* MOVE.L src,Dx *)
OCC.PutF5 (OCC.ADD, L, src, src); (* ADD.L Dx,Dx *)
OCC.PutF5 (OCC.ADD, L, src, src); (* ADD.L Dx,Dx *)
END;
OCC.Move (L, src, dst)
END movePtr;
(*------------------------------------*)
PROCEDURE Assign * (VAR dst, src : OCT.Item; param : BOOLEAN);
VAR f, g : INTEGER; L0, reg, op, s, vsz : LONGINT;
y, z, tag, tdes : OCT.Item; p, q : OCT.Struct; R : OCC.RegState;
R1 : SET; freeDst : BOOLEAN;
(*------------------------------------*)
PROCEDURE IntToReal ();
VAR R : OCC.RegState; f : INTEGER;
BEGIN (* IntToReal *)
IF src.mode = Con THEN src.typ := OCT.linttyp END;
f := src.typ.form;
OCC.LoadRegParams1 (R, src);
IF f = SInt THEN OCI.EXT (W, D0); f := Int END;
IF f = Int THEN OCI.EXT (L, D0) END;
OCC.CallKernel (OCC.kSPFlt);
OCC.RestoreRegisters (R, src);
OCC.Move (L, src, dst)
END IntToReal;
BEGIN (* Assign *)
IF dst.rdOnly THEN OCS.Mark (324) END;
f := dst.typ.form; g := src.typ.form;
IF dst.mode = Con THEN OCS.Mark (56) END;
CASE f OF
Undef :
|
Byte :
IF (g = String) & (src.a1 <= 2) THEN
src.a0 := src.a2; src.typ := OCT.chartyp; g := Char
END;
IF g IN byteSet THEN OCC.Move (B, src, dst)
ELSE OCS.Mark (113)
END
|
Word :
IF (g = String) & (src.a1 <= 2) THEN
src.a0 := src.a2; src.typ := OCT.chartyp; g := Char
END;
IF g IN wordSet THEN OCC.Move (W, src, dst)
ELSIF g IN byteSet THEN moveBW (src, dst, g = SInt)
ELSE OCS.Mark (113)
END
|
Longword :
IF (g = String) & (src.a1 <= 2) THEN
src.a0 := src.a2; src.typ := OCT.chartyp; g := Char
END;
IF g IN lwordSet THEN OCC.Move (L, src, dst)
ELSIF g IN wordSet THEN moveWL (src, dst, g = Int)
ELSIF g IN byteSet THEN moveBL (src, dst, g = SInt)
ELSE OCS.Mark (113)
END
|
Bool :
IF src.mode = Coc THEN
IF (dst.mode = Reg) & (dst.a0 IN AdrRegs) THEN
y := dst; OCC.GetDReg (dst, NIL)
ELSE y.mode := Undef
END;
IF
((src.a1 = 0) & (src.a2 = 0)) OR (src.a0 IN {OCC.T, OCC.F})
THEN
op := OCC.Scc + (src.a0 * 100H); OCC.PutF3 (op, dst)
ELSE
op := OCC.Bcc + (OCC.invertedCC (src.a0) * 100H);
OCC.PutWord (op); OCC.PutWord (src.a2); (* Bcc 1$ *)
src.a2 := OCC.pc - 2; OCC.FixLink (src.a1);
z := dst; OCC.PutF3 (OCC.ST, z); (* ST <dst> *)
L0 := OCC.pc; OCC.PutWord (6000H); (* BRA.S 2$ *)
OCC.FixLink (src.a2);
z := dst; OCC.PutF3 (OCC.SF, z); (* 1$ SF <dst> *)
OCC.PatchWord (L0, OCC.pc - L0 - 2); (* 2$ *)
END;
IF y.mode # Undef THEN
OCC.Move (L, dst, y); OCI.Unload (dst) (*OCI.Unload (y)*)
END
ELSIF g = Bool THEN
IF src.mode = Con THEN
IF (dst.mode = Reg) & (dst.a0 IN AdrRegs) THEN
y := dst; OCC.GetDReg (dst, NIL)
ELSE y.mode := Undef
END;
IF src.a0 = 0 THEN op := OCC.SF ELSE op := OCC.ST END;
OCC.PutF3 (op, dst);
IF y.mode # Undef THEN
OCC.Move (L, dst, y); OCI.Unload (dst) (*OCI.Unload (y)*)
END
ELSE
OCC.Move (B, src, dst)
END
ELSE OCS.Mark (113)
END
|
Char, SInt :
IF (g = String) & (src.a1 <= 2) THEN
src.a0 := src.a2; src.typ := OCT.chartyp; g := Char
END;
IF (g = f) OR (g = Byte) THEN OCC.Move (B, src, dst)
ELSE OCS.Mark (113)
END
|
Int :
IF g IN {Int, Word} THEN OCC.Move (W, src, dst)
ELSIF g = SInt THEN moveBW (src, dst, TRUE)
ELSE OCS.Mark (113)
END
|
LInt :
IF g IN {LInt, Longword, AdrTyp} THEN OCC.Move (L, src, dst)
ELSIF g = Int THEN moveWL (src, dst, TRUE)
ELSIF g = SInt THEN moveBL (src, dst, TRUE)
ELSE OCS.Mark (113)
END
|
BSet, WSet, Set :
IF g = f THEN OCC.Move (src.typ.size, src, dst)
ELSIF (g IN {BSet, WSet, Set}) & (src.mode = Con) THEN
IF (f = BSet) & ((src.a0 < -128) OR (src.a0 > 255)) THEN
OCS.Mark (113)
ELSIF (f = WSet) & ((src.a0 < -32768) OR (src.a0 > 65535)) THEN
OCS.Mark (113)
ELSE
OCC.Move (dst.typ.size, src, dst)
END
ELSE OCS.Mark (113)
END
|
Real :
IF g = Real THEN OCC.Move (L, src, dst)
ELSIF g IN intSet THEN IntToReal ()
ELSE OCS.Mark (113)
END
|
LReal :
IF g = LReal THEN OCC.Move (L, src, dst)
ELSIF g = Real THEN OCC.Move (L, src, dst)
ELSIF g IN intSet THEN IntToReal ()
ELSE OCS.Mark (113)
END
|
Pointer :
IF (dst.typ = src.typ) OR (g = NilTyp) THEN
p := dst.typ.BaseTyp;
IF p = NIL THEN OCS.Mark (966); HALT (966) END;
IF p.form = DynArr THEN
IF param THEN
IF g = NilTyp THEN
WHILE (p # NIL) & (p.form = DynArr) DO
OCC.Move (L, src, dst);
p := p.BaseTyp
END;
ELSIF src.mode = RList THEN
ExtendStack (p.size); dst.mode := RegI; dst.a1 := 0;
ELSE
IF src.mode IN {Ind, IndX, RegI, RegX} THEN
INC (src.a1, p.adr)
ELSE
INC (src.a0, p.adr)
END;
WHILE (p # NIL) & (p.form = DynArr) DO
OCC.Move (L, src, dst);
IF src.mode IN {Ind, IndX, RegI, RegX} THEN DEC (src.a1, 4)
ELSE DEC (src.a0, 4)
END;
p := p.BaseTyp
END
END;
OCC.Move (L, src, dst)
ELSE
IF g = NilTyp THEN
IF dst.mode = RList THEN
R1 := SYS.VAL (SET, dst.a0); reg := D0; dst.mode := Reg;
WHILE reg <= A7 DO
IF reg IN R1 THEN
dst.a0 := reg; OCC.Move (L, src, dst)
END;
INC (reg)
END
ELSE
WHILE (p # NIL) & (p.form = DynArr) DO
OCC.Move (L, src, dst);
IF dst.mode IN {Ind, IndX, RegI, RegX} THEN INC (dst.a1, 4)
ELSE INC (dst.a0, 4)
END;
p := p.BaseTyp
END;
OCC.Move (L, src, dst)
END
ELSIF (src.mode = RList) OR (dst.mode = RList) THEN
OCC.Move (L, src, dst)
ELSE
moveBlock (src, dst, dst.typ.size)
END
END;
ELSE OCC.Move (L, src, dst)
END
ELSIF
(g = Pointer) & (OCT.Tagged (src.typ) = OCT.Tagged (dst.typ))
THEN
p := dst.typ.BaseTyp; q := src.typ.BaseTyp;
IF (p.form = Record) & (q.form = Record) THEN
WHILE (q # p) & (q # NIL) DO q := q.BaseTyp END;
IF q # NIL THEN movePtr (src, dst)
ELSE OCS.Mark (113)
END
ELSE OCS.Mark (113)
END
ELSIF (g IN {AdrTyp, BPtrTyp}) & ~OCT.Tagged (dst.typ) THEN
movePtr (src, dst)
ELSE OCS.Mark (113)
END
|
PtrTyp :
IF
( (g = Pointer) & (src.typ.sysflg = OberonFlag)
& (src.typ.BaseTyp # NIL) & (src.typ.BaseTyp.form # DynArr) )
OR (g IN {PtrTyp, NilTyp})
THEN
OCC.Move (L, src, dst)
ELSE OCS.Mark (113)
END
|
AdrTyp :
IF
((g = Pointer) & (src.typ.sysflg IN {M2Flag, CFlag, AsmFlag}))
OR (g IN {AdrTyp, NilTyp})
THEN
movePtr (src, dst)
ELSE OCS.Mark (113)
END
|
BPtrTyp :
IF
((g = Pointer) & (src.typ.sysflg = BCPLFlag))
OR (g IN {BPtrTyp, NilTyp})
THEN
movePtr (src, dst)
ELSE OCS.Mark (113)
END
|
Array :
IF dst.mode # Pointer THEN
IF dst.typ = src.typ THEN
moveBlock (src, dst, dst.typ.size)
ELSIF (g = String) & (dst.typ.BaseTyp = OCT.chartyp) THEN
freeDst := FALSE;
IF dst.mode = Push THEN
ExtendStack (dst.typ.size);
y.mode := Reg; y.a0 := dst.a0;
OCC.GetAReg (dst, NIL); OCC.Move (L, y, dst);
dst.mode := RegI; dst.a1 := 0;
freeDst := TRUE
END;
z.mode := Con; z.typ := OCT.inttyp; z.a0 := src.a1 - 1;
vsz := dst.typ.n - 1; IF z.a0 > vsz THEN OCS.Mark (114) END;
OCI.CopyString (src, dst, z);
IF freeDst THEN OCC.FreeReg (dst) END
ELSE
OCS.Mark (113)
END
ELSE
OCS.Mark (904)
END
|
DynArr :
IF param THEN (* formal parameter is open array *)
IF dst.mode = Reg THEN
(* Register parameter, address only *)
IF
(dst.typ.BaseTyp = OCT.bytetyp)
OR ((g = String) & (dst.typ.BaseTyp.form = Char))
OR ((g IN {Array, DynArr})
& (src.typ.BaseTyp = dst.typ.BaseTyp))
THEN
IF (g = String) & (dst.typ.BaseTyp.form = Char) THEN
IF src.a1 = 2 THEN OCC.AllocStringFromChar (src) END;
IF src.a1 = 1 THEN (* Pass NIL for an empty string *)
src.mode := Con; src.a0 := 0; OCC.Move (L, src, dst)
ELSE
OCI.MoveAdr (src, dst)
END
ELSE
OCI.MoveAdr (src, dst)
END;
ELSE
OCS.Mark (59)
END
ELSE
IF (g = String) & (dst.typ.BaseTyp.form = Char) THEN
Leng (dst, src.a1);
IF src.a1 < 3 THEN OCC.AllocStringFromChar (src) END
ELSIF src.mode >= Abs THEN
OCS.Mark (59)
ELSE
DynArrBnd (dst.typ, src, FALSE)
END;
IF (g = DynArr) OR (src.mode IN {Ind, IndX}) THEN
OCI.MoveAdr (src, dst)
ELSE
OCC.PutF3 (OCC.PEA, src)
END
END
ELSE
OCS.Mark (113)
END
|
Record :
(* IF (dst.mode = Reg) (*& (src.typ.size > PtrSize)*) THEN *)
(* OCS.Mark (904) *)
(* ELSE *)
IF dst.typ # src.typ THEN
IF g = Record THEN
q := src.typ.BaseTyp;
WHILE (q # NIL) & (q # dst.typ) DO q := q.BaseTyp END;
IF q = NIL THEN OCS.Mark (113) END
ELSE OCS.Mark (113)
END
END;
IF
(dst.typ.sysflg = OberonFlag)
& OCS.pragma [OCS.typeChk] & ~param
& ( ((dst.mode = Ind) OR (dst.mode = RegI))
& (dst.obj = OCC.wasderef)
(* p^ := *)
OR (dst.mode = Ind) & (dst.obj # NIL)
& (dst.obj # OCC.wasderef))
(* varpar := *)
THEN
R := OCC.regState; tag := dst; tag.typ := OCT.tagtyp;
IF dst.obj = OCC.wasderef THEN tag.a1 := -4
ELSE tag.mode := Var; INC (tag.a0, 4)
END;
tdes.mode := Con; tdes.a0 := 0; tdes.a1 := 0;
tdes.typ := OCT.tagtyp; tdes.label := dst.typ.label;
OCI.Adr (tdes); OCI.CMP (L, tdes, tag);
OCC.TrapCC (OCC.TypeCheck, OCC.NE);
OCC.FreeRegs (R)
END;
moveBlock (src, dst, dst.typ.size)
(* END *)
|
ProcTyp :
IF (dst.typ = src.typ) OR (g = NilTyp) THEN
IF (src.mode = XProc)
OR ((OCM.SmallData OR OCM.Resident) & (src.mode = LProc))
THEN
OCI.MoveAdr (src, dst)
ELSIF src.mode IN {LProc, TProc, LibCall, AProc, M2Proc, CProc} THEN
OCS.Mark (119)
ELSE OCC.Move (L, src, dst)
END;
ELSIF (src.mode = XProc)
OR ((OCM.SmallData OR OCM.Resident) & (src.mode = LProc))
THEN
(* procedure dest to proc. variable, check compatibility *)
IF dst.typ.BaseTyp = src.typ THEN
CompareParLists (dst.typ.link, src.obj.link);
OCI.MoveAdr (src, dst)
ELSE OCS.Mark (118)
END
ELSIF src.mode IN {LProc, TProc, LibCall, AProc, M2Proc, CProc} THEN
OCS.Mark (119)
ELSE OCS.Mark (111)
END
|
TagTyp :
IF (f = g) OR (g = NilTyp) THEN OCC.Move (L, src, dst)
ELSE OCS.Mark (111)
END
|
NoTyp, NilTyp : OCS.Mark (111)
|
ELSE
OCS.Mark (1016); OCS.Warn (f)
END; (* CASE f *)
OCC.ForgetObj (dst.obj);
OCI.Unload (src)
END Assign;
(*------------------------------------*)
PROCEDURE RegsUsed ( fpar : OCT.Object ) : SET;
VAR result : SET;
BEGIN (* RegsUsed *)
result := {};
WHILE (fpar # NIL) & OCT.IsParam (fpar) DO
INCL (result, fpar.a0); fpar := fpar.link
END;
RETURN result
END RegsUsed;
(*------------------------------------*)
PROCEDURE PrepCall *
( VAR x : OCT.Item;
VAR fpar : OCT.Object;
VAR mask : SET );
VAR y : OCT.Item;
BEGIN (* PrepCall *)
mask := OCC.AllRegs;
IF x.mode IN {LProc, XProc, AProc, LibCall, M2Proc, CProc} THEN
fpar := x.obj.link;
IF x.mode IN {LibCall, AProc} THEN
mask := OCC.ScratchRegs + RegsUsed (fpar);
IF x.mode = LibCall THEN
INCL (mask, A6)
END
END
ELSIF x.mode = TProc THEN
fpar := x.obj.link.link;
ELSIF (x.typ # NIL) & (x.typ.form = ProcTyp) THEN
fpar := x.typ.link
ELSE
OCS.Mark (121); fpar := NIL; x.typ := OCT.undftyp
END
END PrepCall;
(* ---------------------------------- *)
PROCEDURE VarArgParam *
( VAR ap : OCT.Item;
fpo : OCT.Object;
load : BOOLEAN );
VAR fp, reg : OCT.Item;
BEGIN (* VarArgParam *)
fp.mode := Push; fp.a0 := A7; fp.typ := fpo.typ; fp.rdOnly := FALSE;
Assign (fp, ap, TRUE);
IF load THEN
fp.mode := Reg; reg.mode := Reg; reg.a0 := fpo.a0;
OCC.ReserveReg (reg.a0, NIL);
OCC.Move (L, fp, reg)
END;
END VarArgParam;
(*------------------------------------*)
PROCEDURE Param * (VAR ap : OCT.Item; fpo : OCT.Object; mode : INTEGER);
VAR
fp, t : OCT.Item; q : OCT.Struct; freeFp : BOOLEAN; f, g : INTEGER;
s : LONGINT;
BEGIN (* Param *)
IF mode IN {LibCall, AProc} THEN (* Register parameter *)
fp.mode := Reg; fp.a0 := fpo.a0
ELSE (* Stack parameter *)
fp.mode := Push; fp.a0 := SP
END;
fp.typ := fpo.typ; fp.rdOnly := FALSE;
f := fpo.typ.form; g := ap.typ.form;
IF fpo.mode = Ind THEN (* VAR parameter *)
IF ap.mode >= Con THEN OCS.Mark (122)
ELSIF ap.rdOnly THEN OCS.Mark (324)
END;
IF fp.typ.form = DynArr THEN
IF fp.mode = Reg THEN
OCI.MoveAdr (ap, fp)
ELSE
IF mode # CProc THEN DynArrBnd (fp.typ, ap, TRUE) END;
IF (ap.typ.form = DynArr) OR (ap.mode IN {Ind, IndX}) THEN
OCI.MoveAdr (ap, fp)
ELSE
OCC.PutF3 (OCC.PEA, ap)
END
END
ELSIF (fp.typ.form = Record) & (ap.typ.form = Record) THEN
q := ap.typ; WHILE (q # fp.typ) & (q # NIL) DO q := q.BaseTyp END;
IF q # NIL THEN
IF (ap.mode = Ind) & (ap.obj # NIL) & (ap.obj # OCC.wasderef) THEN
(* actual parameter is a VAR parameter *)
ap.mode := Var;
IF q.sysflg = OberonFlag THEN
INC (ap.a0, 4); OCC.Move (L, ap, fp);
IF ap.mode = Var THEN DEC (ap.a0, 4) ELSE DEC (ap.a1, 4) END;
END;
OCC.Move (L, ap, fp)
ELSIF
((ap.mode = Ind) OR (ap.mode = RegI)) & (ap.obj = OCC.wasderef)
THEN
(* actual parameter is a dereferenced pointer *)
IF q.sysflg = OberonFlag THEN
ap.a1 := -4; OCC.Move (L, ap, fp);
ap.a1 := 0;
END;
OCI.MoveAdr (ap, fp)
ELSE
IF q.sysflg = OberonFlag THEN
t.mode := Con; t.a0 := 0; t.a1 := 0; t.typ := OCT.tagtyp;
t.label := ap.typ.label;
OCC.PutF3 (OCC.PEA, t)
END;
IF fp.mode = Reg THEN OCI.MoveAdr (ap, fp)
ELSE OCC.PutF3 (OCC.PEA, ap)
END
END
ELSE OCS.Mark (111)
END
ELSIF
(ap.typ = fp.typ)
OR ((f = Byte) & (g IN {Char, SInt, BSet}))
OR ((f = Word) & (g IN wordSet))
OR ((f = Longword) & (g IN lwordSet))
OR ((f = PtrTyp) & (g = Pointer) & (ap.typ.sysflg = OberonFlag))
OR ((f = AdrTyp) & (g = Pointer) & (ap.typ.sysflg IN {M2Flag, CFlag, AsmFlag}))
OR ((f = BPtrTyp) & (g = Pointer) & (ap.typ.sysflg = BCPLFlag))
THEN
IF (ap.mode IN {Ind, IndX}) OR (fp.mode = Reg) THEN
OCI.MoveAdr (ap, fp)
ELSE
OCC.PutF3 (OCC.PEA, ap)
END
ELSE OCS.Mark (123)
END;
OCI.Unload (ap)
ELSE
Assign (fp, ap, TRUE);
END;
IF mode IN {LibCall, AProc} THEN (* Reserve parameter's register *)
OCC.ReserveReg (fp.a0, NIL)
END
END Param;
(*------------------------------------*)
PROCEDURE DeRef (VAR x : OCT.Item);
VAR t1, t2 : OCT.Item;
BEGIN (* DeRef *)
IF (x.mode <= RegX) & (x.typ.form = Pointer) THEN
IF OCC.InAdrReg (x.obj) THEN
OCC.GetAReg (x, x.obj); x.mode := RegI
ELSE
t1 := x; t1.obj := NIL; t1.typ := OCT.ptrtyp; OCC.GetAReg (x, x.obj);
IF OCS.pragma [OCS.nilChk] THEN
OCC.GetDReg (t2, NIL); OCC.Move (L, t1, t2); (* MOVE.L x,Dn *)
OCC.TrapCC (OCC.NilCheck, OCC.EQ);
OCC.Move (L, t2, x); OCI.Unload (t2) (* MOVEA.L Dn, An *)
ELSE
OCC.Move (L, t1, x); (* MOVEA.L x, An *)
END;
x.mode := RegI
END;
x.typ := x.typ.BaseTyp; x.obj := OCC.wasderef; x.rdOnly := FALSE;
x.a2 := 0
ELSE
OCS.Mark (84)
END;
x.a1 := 0
END DeRef;
(*------------------------------------*)
PROCEDURE Receiver *
( mode : SHORTINT;
VAR x : OCT.Item;
rcvr : OCT.Object;
mask : SET );
VAR t1 : OCT.Item; R : OCC.RegState;
BEGIN (* Receiver *)
IF mode = TProc THEN
t1 := x;
IF (t1.typ.form = Pointer) & (rcvr.mode = Ind) THEN DeRef (t1) END;
R := OCC.regState; Param (t1, rcvr, TProc); OCC.regState.regs := R.regs
ELSIF (OCM.SmallData OR OCM.Resident) & (A4 IN mask) THEN
OCC.ReserveReg (A6, NIL);
t1.mode := Reg; t1.a0 := A6; OCC.Move (L, x, t1);
END;
END Receiver;
(*------------------------------------*)
PROCEDURE Call *
( VAR x, rcvr : OCT.Item;
stackload : LONGINT;
mask : SET );
VAR y, z : OCT.Item; offset : LONGINT;
BEGIN (* Call *)
IF x.mode = LProc THEN
IF x.lev > 0 THEN
y.mode := Var; y.typ := OCT.linttyp;
IF x.lev = OCC.level THEN
y.lev := x.lev; y.a0 := 0; OCC.PutF3 (OCC.PEA, y)
ELSE
y.lev := x.lev + 1; y.a0 := 8; z.mode := Push; z.a0 := SP;
OCC.Move (L, y, z)
END
END;
OCC.PutWord (OCC.BSR); OCC.PutWordRef (0, x.label)
ELSIF x.mode IN {XProc, M2Proc, CProc, AProc} THEN
IF OCM.SmallCode OR ((x.mode = XProc) & (x.lev = 0)) THEN
OCC.PutWord (OCC.BSR); OCC.PutWordRef (0, x.label)
ELSE
OCC.PutF3 (OCC.JSR, x)
END
ELSIF x.mode = TProc THEN
IF x.a2 < 0 THEN (* Super-call, call directly *)
x.lev := -x.obj.link.typ.mno;
IF OCM.SmallCode OR (x.lev = 0) THEN
OCC.PutWord (OCC.BSR); OCC.PutWordRef (0, x.label)
ELSE
x.mode := XProc; OCC.PutF3 (OCC.JSR, x)
END
ELSE
y := rcvr;
IF y.typ.form = Pointer THEN DeRef (y) END;
IF x.obj.a0 >= 0 THEN offset := x.obj.a0 * (-4)
ELSE offset := x.obj.a2
END;
IF (y.mode IN {RegI, Ind}) & (y.obj = OCC.wasderef) THEN
(* rcvr is dereferenced pointer *)
OCC.GetAReg (z, NIL); y.a1 := -4; OCC.Move (L, y, z);
y.mode := RegI; y.a0 := z.a0; y.a1 := offset; OCC.Move (L, y, z);
IF offset >= 0 THEN x.obj.a2 := OCC.pc - 2 END;
z.mode := RegI; z.a1 := 0; OCC.PutF3 (OCC.JSR, z)
ELSIF (y.mode = Ind) & (y.obj # NIL) & (y.obj # OCC.wasderef) THEN
(* rcvr is record variable parameter *)
y.mode := Var; INC (y.a0, 4);
OCC.GetAReg (z, NIL); OCC.Move (L, y, z);
y.mode := RegI; y.a0 := z.a0; y.a1 := offset; OCC.Move (L, y, z);
IF offset >= 0 THEN x.obj.a2 := OCC.pc - 2 END;
z.mode := RegI; z.a1 := 0; OCC.PutF3 (OCC.JSR, z);
ELSE
(* rcvr is record variable *)
x.lev := -x.obj.link.typ.mno;
IF OCM.SmallCode OR (x.lev = 0) THEN
OCC.PutWord (OCC.BSR); OCC.PutWordRef (0, x.label)
ELSE
x.mode := XProc; OCC.PutF3 (OCC.JSR, x)
END
END
END
ELSIF x.mode = LibCall THEN
y.a0 := A6;
IF ~((OCM.SmallData OR OCM.Resident) & (A4 IN mask)) THEN
OCC.ReserveReg (A6, NIL);
y.mode := Reg; OCC.Move (L, rcvr, y);
END;
OCC.UnReserveReg (A6);
y.mode := RegI; y.a1 := x.a0; OCC.PutF3 (OCC.JSR, y)
ELSIF (x.mode < Con) & (x.typ # OCT.undftyp) THEN (* procedure variable *)
IF OCC.InAdrReg (x.obj) THEN
OCC.GetAReg (x, x.obj)
ELSE
y := x; y.typ := OCT.ptrtyp; OCC.GetAReg (x, x.obj);
IF OCS.pragma [OCS.nilChk] THEN
OCI.Load (y); (* MOVE.L x,Dn *)
OCC.TrapCC (OCC.NilCheck, OCC.EQ)
END;
OCC.Move (L, y, x); OCI.Unload (y)
END;
x.mode := RegI; x.a1 := 0;
OCC.PutF3 (OCC.JSR, x);
x.typ := x.typ.BaseTyp
ELSE
OCS.Mark (121)
END;
IF x.mode IN {LibCall, CProc, AProc} THEN
IF stackload > 0 THEN
IF stackload <= 8 THEN
y.mode := Reg; y.a0 := SP;
OCC.PutF7 (OCC.ADDQ, L, stackload, y)
ELSE
y.mode := RegI; y.a0 := SP; y.a1 := stackload;
OCC.PutF2 (OCC.LEA, y, SP)
END
END
END
END Call;
(*------------------------------------*)
PROCEDURE Result * (VAR x : OCT.Item; typ : OCT.Struct);
VAR res : OCT.Item; R : SET; reg : INTEGER;
BEGIN (* Result *)
IF
(typ.form = Pointer) & (typ.sysflg = OberonFlag)
& (typ.BaseTyp # NIL) & (typ.BaseTyp.form = DynArr)
THEN
res.mode := RList; R := {}; reg := D0;
WHILE (reg * 4) < typ.size DO INCL (R, reg); INC (reg) END;
res.a0 := SYS.VAL (LONGINT, R)
ELSE
res.mode := Reg; res.a0 := D0
END;
res.typ := typ; res.rdOnly := FALSE;
Assign (res, x, FALSE);
returnFound := TRUE
END Result;
(*------------------------------------*)
PROCEDURE CaseIn * (VAR x : OCT.Item; VAR L0 : LONGINT);
BEGIN (* CaseIn *)
IF ~(x.typ.form IN caseSet) THEN OCS.Mark (125) END;
OCI.Load (x); OCC.UnReserveReg (x.a0); L0 := 0; FJ (L0)
END CaseIn;
(*------------------------------------*)
PROCEDURE CaseOut *
( VAR x : OCT.Item;
L0, L1, L2 : LONGINT;
n : INTEGER;
VAR tab : ARRAY OF LabelRange);
VAR labItem, y, z : OCT.Item; i : INTEGER; L3 : LONGINT;
BEGIN (* CaseOut *)
labItem.mode := Con; labItem.typ := x.typ; i := 0;
OCC.FixLink (L0); (* fixup jump from case expression *)
WHILE i < n DO
IF tab [i].low = tab [i].high THEN
y := x; labItem.a0 := tab [i].low; OCE.Op (neq, y, labItem, FALSE);
CBJ (y, tab [i].label)
ELSE
L3 := 0; y := x; labItem.a0 := tab [i].low;
OCE.Op (geq, y, labItem, FALSE); CFJ (y, L3); z := x;
labItem.a0 := tab [i].high; OCE.Op (gtr, z, labItem, FALSE);
CBJ (z, tab [i].label); OCC.fixup (L3)
END;
INC (i)
END;
BJ (L2); (* jump to code for else part *)
OCC.FixLink (L1); (* fixup jumps from individual cases *)
END CaseOut;
(*------------------------------------*)
PROCEDURE BeginFor *
( VAR control, low, high, step : OCT.Item;
VAR R : OCC.RegState;
VAR L0, L1 : LONGINT );
VAR f, g, h, i : INTEGER; x, y : OCT.Item;
BEGIN (* BeginFor *)
f := control.typ.form; g := low.typ.form; h := high.typ.form;
i := step.typ.form;
IF (f IN intSet) & (g IN intSet) & (h IN intSet) & (i IN intSet) THEN
IF low.mode = Con THEN
IF (f = Int) & (g = LInt) THEN OCS.Mark (317)
ELSIF (f = SInt) & (g # SInt) THEN OCS.Mark (317)
END;
low.typ := control.typ
END;
IF high.mode = Con THEN
IF (f = Int) & (h = LInt) THEN OCS.Mark (317)
ELSIF (f = SInt) & (h # SInt) THEN OCS.Mark (317)
END;
high.typ := control.typ
ELSE OCI.Load (high)
END;
IF (f = Int) & (i = LInt) THEN OCS.Mark (317)
ELSIF (f = SInt) & (i # SInt) THEN OCS.Mark (317)
END;
step.typ := control.typ;
IF (low.mode = Con) & (high.mode = Con) THEN
IF (step.a0 > 0) & (high.a0 < low.a0) THEN OCS.Mark (318)
ELSIF (step.a0 < 0) & (low.a0 < high.a0) THEN OCS.Mark (318)
END
END;
x := control; Assign (x, low, FALSE);
OCC.ForgetRegs; OCC.FreeRegs (R);
IF high.mode = Reg THEN OCC.ReserveReg (high.a0, NIL) END;
L0 := OCC.pc; x := control; y := high;
IF high.mode = Con THEN
IF step.a0 > 0 THEN OCE.Op (leq, x, y, FALSE);
ELSE OCE.Op (geq, x, y, FALSE);
END;
CFJ (x, L1)
ELSE
IF step.a0 > 0 THEN OCE.Op (geq, y, x, FALSE);
ELSE OCE.Op (leq, y, x, FALSE);
END;
CFJ (y, L1)
END;
END
END BeginFor;
(*------------------------------------*)
PROCEDURE EndFor *
( VAR control, step, high : OCT.Item; L0, L1 : LONGINT );
BEGIN (* EndFor *)
IF step.a0 > 0 THEN OCC.PutF5 (OCC.ADD, step.typ.size, step, control)
ELSE
step.a0 := -step.a0; OCC.PutF5 (OCC.SUB, step.typ.size, step, control)
END;
(*IF OCS.overflowCheck THEN OCC.PutWord (OCC.TRAPV) END;*)
BJ (L0); OCC.FixLink (L1);
IF high.mode = Reg THEN OCC.UnReserveReg (high.a0) END;
END EndFor;
END OCH.
(***************************************************************************
$Log: OCH.mod $
Revision 5.25 1995/06/15 18:15:13 fjc
- Fixed YARAB (Yet Another Register Allocation Bug)
affecting type-bound procedures.
Revision 5.24 1995/06/04 22:51:00 fjc
- Fixed loading of A6 for library calls where A4 is used
for parameters.
Revision 5.23 1995/06/03 00:36:42 fjc
- Amiga Library calls now load the base variable into A6
*before* loading any parameters.
Revision 5.22 1995/06/02 18:43:09 fjc
- Implemented the SMALLDATA, RESIDENT and REGISTER options.
Revision 5.22 1995/05/29 21:22:28 fjc
- Various changes to support the SMALLDATA and RESIDENT
options.
Revision 5.21 1995/05/13 23:09:43 fjc
- Changed INTEGER to LONGINT where necessary.
Revision 5.20 1995/05/08 17:04:24 fjc
- OCI.IsParam() --> OCT.IsParam()
Revision 5.19 1995/04/23 17:59:39 fjc
- Merging 5.26 & 5.27
Revision 5.17 1995/04/02 13:53:40 fjc
- Numerous changes to implement the small data model.
Revision 5.16 1995/03/25 17:08:00 fjc
- Added stripped-down version of OCE.DeRef() to be used
by Receiver() and Call().
Revision 5.15 1995/03/23 18:27:06 fjc
- Modifications to Call(), BeginFor() and EndFor().
Revision 5.14 1995/03/13 11:36:30 fjc
- LibCalls now reserve the A6 register as a precaution,
probably unnecessary.
Revision 5.13 1995/03/09 19:12:00 fjc
- Incorporated changes from 5.22.
Revision 5.12 1995/02/27 17:08:00 fjc
- Removed tracing code.
- Implemented SMALLCODE option.
- Changed to use new register handling procedures.
Revision 5.11.1.1 1995/03/08 19:24:14 fjc
- OC 5.22
Revision 5.11 1995/01/26 00:17:17 fjc
- Release 1.5
Revision 5.10 1995/01/03 21:23:57 fjc
- Changed OCG to OCM.
Revision 5.9 1994/12/16 17:38:11 fjc
- Changed Symbol to Label.
- Changed Call() to generate a fixup list for calls to
type-bound procedures which have not yet been allocated
a slot.
Revision 5.8 1994/11/13 11:35:10 fjc
- Changed Assign() to make SYSTEM.PTR incompatible with
POINTER TO ARRAY OF ...
Revision 5.7 1994/10/23 16:26:35 fjc
- Rewrote ModulePrologue() to call module Kernel's
initialisation code.
- All calls to the RTS are now through OCC.CallKernel().
- Rewrote code for pointer assignments.
- Fixed bug in code for procedure variable assignments.
- Merged CallLibCall() and CallTypeBound() into Call().
Revision 5.6 1994/09/25 18:05:21 fjc
- Changed to reflect new object modes and system flags,
espcially:
- Merged Param() and RegParam().
- Overhauled handling of pointer assignments.
Revision 5.5 1994/09/19 23:10:05 fjc
- Re-implemented Amiga library calls
Revision 5.4 1994/09/15 19:43:51 (fnc
-(Merged in bug fix from 4.17.
Revision 5.3 1994/09/15 10:40:23 fjc
- Replaces switches with pragmas.
- Implemented the EntryExitCode pragma and the INITIALISE
and MAIN options.
Revision 5.2 1994/09/08 10:52:07 fjc
- Changed to use pragmas/options.
Revision 5.1 1994/09/03 19:29:08 fjc
- Bumped version number
***************************************************************************)